########################################################################
# A generic Makefile for C++ programs
#
# Originally Created by Bob Ji
# April 12, 2012
########################################################################
#
# Usage:
#
# Synopsis:
#
# make [DEBUG=0|1] [TEST=0|1]
#
# Options:
# Debug=0|1 turns on all debug information [default 0]
#
# Supported Platform: MINGW32, CYGWIN, Linux
#
########################################################################

# System information
SUPPORTED_PLATFORMS := Linux, CYGWIN, MINGW32
export PLATFORM := $(findstring $(shell uname -s | sed 's,_.*,,'),$(SUPPORTED_PLATFORMS))
ifeq ($(PLATFORM),"")
    $(error Unknown platform: $(shell uname -s))
endif
# target name. Usually, only TARGET_NAME need to be changed
TARGET_NAME := mna
# include path. Default: .
INCLUDE_DIRS := .
# target path. Default: .
TARGET_PATH := .
# C++ compiler
ifeq ($(PLATFORM),CYGWIN)
    export CC := g++
else
    export CC := g++
endif
# Archieve utility
export AR := ar
export ARFLAGS := rus
# Lexer
export FLEX := flex
export BISON := bison
# case-insensitive parser
export FLEXFLAGS := -i
export BISONFLAGS := --define --yacc

# debug flag. Note: comment out the line below for the release version
ifeq ($(DEBUG),1)
    CONFIG := debug
    export DEBUG_FLAG := -O0 -ggdb -DDEBUG
    export FLEXFLAGS += -d
else
    CONFIG := release
    export DEBUG_FLAG := -O3 -DNDEBUG
endif

# control testing code
ifeq ($(TEST),1)
    export DEBUG_FLAG += -DTEST
endif

# libraries
LDFLAGS := -lm

# all compiler flags
export CFLAGS := -Wall -Wno-unused-variable $(DEBUG_FLAG)

# The excutable has ".exe" suffix on the CYGWIN and MINGW32 platforms.
ifeq ($(PLATFORM),Linux)
    TARGET_SUFFIX :=
else
    TARGET_SUFFIX := .exe
endif
# construct the full target name
TARGET := $(TARGET_PATH)/$(TARGET_NAME)-$(PLATFORM)-$(CONFIG)$(TARGET_SUFFIX)

# the prerequisite of each source file will be generated automatically
# the suffix of source files
export SRCS_SUFFIX := .cpp
# the suffix of rerequisite files
export PREREQ_SUFFIX := .d

SRCS := $(wildcard *$(SRCS_SUFFIX))
OBJS := $(patsubst %$(SRCS_SUFFIX),%.o,$(wildcard *$(SRCS_SUFFIX)))
PREREQS := $(SRCS:%$(SRCS_SUFFIX)=%$(PREREQ_SUFFIX))

# subdirectory
#SUB_DIR := sub
#export SUB_LIB := sub.a

.PHONY: all
all: $(TARGET)

ifneq "$(MAKECMDGOALS)" "clean"
ifneq "$(MAKECMDGOALS)" "distclean"
    sinclude $(PREREQS)
endif
endif

$(TARGET): $(OBJS)
	@echo Building $(TARGET) ...; echo -e "\n"
	$(CC) -o $@ $^ $(LDFLAGS)
	@echo -e "\n"; echo "Successfully build $(TARGET) ."

%$(PREREQ_SUFFIX): %$(SRCS_SUFFIX)
	$(CC) -MM $< $(CFLAGS) $(addprefix -I, $(INCLUDE_DIRS)) > $@.$$$$; \
	sed 's,\($*\)\.o[:]*,\1.o $@:,g' < $@.$$$$ > $@; \
	$(RM) $@.$$$$

%.o: %$(SRCS_SUFFIX)
	$(CC) -c $< -o $@ $(CFLAGS) $(addprefix -I,$(INCLUDE_DIRS))

.PHONY: clean distclean

clean:
	$(RM) $(OBJS) $(PREREQS)

distclean: clean
	$(RM) $(TARGET_PATH)/$(TARGET_NAME)-$(PLATFORM)-*$(TARGET_SUFFIX)

